package com.nulldev.util.web.HttpClient.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;

import com.nulldev.util.JVM.Arguments;
import com.nulldev.util.data.CompressionAPI.thirdparty.airlift.zstd.ZstdInputStream;
import com.nulldev.util.data.CompressionAPI.thirdparty.lzc.LZCInputStream;
import com.nulldev.util.data.CompressionAPI.thirdparty.mig.MiGzInputStream;
import com.nulldev.util.io.IOUtils;

public class HttpStreamUtil {

	private static final boolean ENABLE_PARALLEL_GZIP = Arguments.hasArgument("--HttpClient.enableParallelGZip");
	private static final boolean EXPOSE_ZSTD_SUPPORT = Arguments.hasArgument("--HttpClient.exposeZSTD");

	public static InputStream decode(final InputStream is, final String encoding) throws IOException {
		if (is == null || encoding == null || encoding.isEmpty())
			return is;
		switch (encoding) {
			case "gzip": {
				if (ENABLE_PARALLEL_GZIP) {
					return new MiGzInputStream(is);
				} else {
					return new GZIPInputStream(is, IOUtils.MEMORY_ALLOC_BUFFER);
				}
			}
			case "deflate":
				return new InflaterInputStream(is, new Inflater(true));
			case "compress":
				return new LZCInputStream(is);
			case "zstd":
				return new ZstdInputStream(is);
			case "zstd-d":
				/* TODO: Add support for "Available-Dictionary" and custom dictionaries */
			default:
				return is;
		}
	}

	private static final String SUPPORTED_METHODS = "gzip, deflate";
	private static final String SUPPORTED_METHODS_ZSTD = "gzip, deflate, zstd";

	public static String getSupportedCompressionString() {
		if (EXPOSE_ZSTD_SUPPORT) {
			return SUPPORTED_METHODS_ZSTD;
		} else {
			return SUPPORTED_METHODS;
		}
	}

	public static void __check_valid_buffer_size(final int bufSize) {
		if (bufSize < 8 || bufSize > (1 * 1024 * 1024))
			throw new IllegalArgumentException("Invalid buffer size: " + bufSize);
	}
}
